<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            margin: 0;
            height: 100vh;
            width: 100%;
            display: grid;
        }
        .cell {
            outline: 1px solid red;
        }
        .ball {
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background-color: blue;
        }
    </style>
</head>
<body>
    <!-- <div class="cell">
        <div class="ball"></div>
    </div>
    <div class="cell">
        <div class="ball"></div>
    </div>
    <div class="cell">
        <div class="ball"></div>
    </div>
    <div class="cell">
        <div class="ball"></div>
    </div> -->

    <script>

        function getRangeValue(value, [min, max]) {
            if (value < min) {
                return min;
            }
            if (value > max) {
                return max;
            }
            return value;
        }

        const [rowCount, colCount] = prompt('输入行列，中间用,隔开').split(','); // '3,4'
        document.body.setAttribute('style', `
            grid-template-columns: repeat(${ colCount }, 1fr);
            grid-template-rows: repeat(${ rowCount }, 1fr);
        `);
        // 总共个数
        const count = rowCount * colCount;
        // 创建所有cell
        for (let i = 0; i < count; i++) {
            // 创建cell
            const cell = document.createElement('div'); // <div></div>
            cell.setAttribute('class', 'cell');

            const ball = document.createElement('div'); // <div></div>
            ball.setAttribute('class', 'ball');

            cell.appendChild(ball);
            document.body.appendChild(cell);
        }

        // 拖拽
        let innerX = 0;
        let innerY = 0;
        const vw = window.innerWidth;
        const vh = window.innerHeight;

        const balls = document.querySelectorAll('.ball');

        function onMouseMove(e) {
            const x = e.clientX - innerX;
            const y = e.clientY - innerY;
            const maxX = vw / colCount - balls[0].offsetWidth;
            const maxY = vh / rowCount - balls[0].offsetHeight;;

            const realX = getRangeValue(x, [0, maxX]);
            const realY = getRangeValue(y, [0, maxY]);

            for (const ball of balls) {
                ball.setAttribute('style', `transform: translate(${ realX }px, ${ realY }px);`);
            }
        }

        balls[0].addEventListener('mousedown', function (e) {
            innerX = e.offsetX;
            innerY = e.offsetY;
            // 绑事件
            document.addEventListener('mousemove', onMouseMove);
        });
        balls[0].addEventListener('mouseup', function (e) {
            // 解绑事件
            document.removeEventListener('mousemove', onMouseMove);
        });
    </script>
</body>
</html>